/*
 * PlayerDAO.java
 *
 * Created on 7 August 2007, 22:48
 *
 */

package digitrix.fightclub.data;

import digitrix.fightclub.game.FightClub;
import java.util.Enumeration;
import java.util.Vector;
import javax.microedition.rms.RecordEnumeration;
import javax.microedition.rms.RecordStore;
import javax.microedition.rms.RecordStoreException;

/**
 * The purpose of this class is to store the player details, this includes things such as 
 * selected character, player attributes (strength, experience, speed), also player stats 
 * (fights in total, wins, loses, draws) 
 * The application can only have one player saved to the RMS; when a new player is selected 
 * then all attributes, stats are taken to zero. 
 * @author Josh
 */
public class PlayerDAO {
    
    private static final boolean AUTOMATICALLY_CREATE_PLAYER = true; // temp while developing BT component    
    
    private static PlayerDAO _instance;        
    
    private static final String RS_PLAYER_DETAILS       = "RS_PLAYER"; // recordstore name for player details  
    private static final String RS_PLAYER_STATS_WINS    = "RS_STATS_WINS";  // resorcestore name for player stats
    private static final String RS_PLAYER_STATS_LOSES   = "RS_STATS_LOSES";
    private static final String RS_PLAYER_STATS_DRAWS   = "RS_STATS_DRAWS";
    
    private static final String FIELD_SEPERATOR = "|"; 
    // fields for player details 
    private static final String FIELD_NAME      = "name"; 
    private static final String FIELD_STRENGTH  = "strength"; 
    private static final String FIELD_SPEED     = "speed";
    private static final String FIELD_PLAYER_ID = "playerid";             
    
    // player attributes
    private String _playerName = "Unknown";
    private int _strenth = 0;
    private int _speed = 0;
    private int _playerID = 0; 
    
    // player stats 
    private Vector _wins = null; // hold a list of players names we have won against 
    private Vector _loses = null; // hold a list of players names we have lost against                
    private Vector _draws = null; // hold a list of players names we have drawn against 
            
    private boolean _playerInit = false; 
    
    /** Creates a new instance of PlayerDAO */
    private PlayerDAO() {
        try{
            setPlayerInit(initPlayer());                         
            
            if( isPlayerInit() ){
                initPlayerStats(); 
            }
            else if( AUTOMATICALLY_CREATE_PLAYER ){
                createDefaultPlayer(); 
                _playerInit = true; 
            }
        }
        catch( RecordStoreException rse ){
            _playerInit = false; 
        }        
    }
    
    /** singleton class **/ 
    public static PlayerDAO getInstance(){
        if( _instance == null )
            _instance = new PlayerDAO(); 
        
        return _instance; 
    }
    
    /** temp **/ 
    private void createDefaultPlayer(){
        FightClub.printDebug( "PlayerDAO", "createDefaultPlayer", "creating default player" );
        
        this._playerID = 2;
        this._playerName = "newms"; 
        this._speed = 5;
        this._strenth = 4;
        
        // TODO: app hangs when this is called for the first time
        //savePlayerDetails(); 
    }
    
    /** commit players attributes to the RMS **/ 
    public boolean savePlayerDetails(){
        RecordStore rs = null; 
        RecordEnumeration renum = null; 
        
        boolean success = true; 
        
        try{
            // open recordstore or create one if it does not exist 
            rs = RecordStore.openRecordStore( RS_PLAYER_DETAILS, true );            
            
            // get record enumeration and delete existing records 
            renum = rs.enumerateRecords( null, null, false ); 
            while( renum.hasNextElement() ){
                int recordID = renum.nextRecordId(); 
                rs.deleteRecord( recordID );
            }
            
            // now save the details 
            // player name 
            String data = FIELD_NAME + FIELD_SEPERATOR + _playerName;
            byte[] raw = data.getBytes(); 
            rs.addRecord(raw, 0, raw.length );
            
            // strength 
            data = FIELD_STRENGTH + FIELD_SEPERATOR + _strenth;
            raw = data.getBytes(); 
            rs.addRecord(raw, 0, raw.length );
            
            // speed            
            data = FIELD_SPEED + FIELD_SEPERATOR + _speed;
            raw = data.getBytes(); 
            rs.addRecord(raw, 0, raw.length );
            
            // player id
            data = FIELD_PLAYER_ID + FIELD_SEPERATOR + _playerID;
            raw = data.getBytes(); 
            rs.addRecord(raw, 0, raw.length );
            
        }
        catch( Exception e ){
            success = false; 
            FightClub.getInstance().printError( "PlayerDAO.savePlayerDetails()", e.toString() );
        }
        finally{
            try{
                if( renum != null ) renum.destroy();
                if( rs != null ) rs.closeRecordStore();
            }
            catch( RecordStoreException rse ){
                FightClub.getInstance().printError( "PlayerDAO.savePlayerDetails()", rse.toString() );
            }
        }
        
        return success; 
    }       
    
    //<editor-fold defaultstate="collapsed" desc="private helper methods">
    
    /** 
     * load up the player details; if recordstore found then return true else false 
     * Structure of the string stored into the RMS is 
     * name|{name},  strength|{strength}, 
     *  speed|{speed}, playerid|{playerID}
     **/ 
    private boolean initPlayer() throws RecordStoreException {
        RecordStore rs = null;
        RecordEnumeration renum = null;
        
        boolean success = true; 
        
        try{
            rs = RecordStore.openRecordStore( RS_PLAYER_DETAILS, true );
            renum = rs.enumerateRecords( null, null, false );
            
            boolean hasRecords = false; 
            
            while( renum.hasNextElement() ){
                byte[] raw = renum.nextRecord(); 
                String data = new String( raw );                                
                
                // extract data type (name, strength, speed, or playerid)
                int index = data.indexOf("|"); 
                String type = data.substring( 0, index );
                if( type.equals( FIELD_NAME ) ){
                    hasRecords = true; 
                    _playerName = data.substring( index+1 ); 
                }
                else if( type.equals( FIELD_STRENGTH ) ){
                    hasRecords = true; 
                    _strenth = Integer.parseInt( data.substring( index+1 ) );
                }
                else if( type.equals( FIELD_SPEED ) ){
                    hasRecords = true; 
                    _speed = Integer.parseInt( data.substring( index+1 ) );
                }
                else if( type.equals( FIELD_PLAYER_ID ) ){
                    hasRecords = true; 
                    _playerID = Integer.parseInt( data.substring( index+1 ) );
                }                                    
                
            }   
            
            // make sure we have loaded data otherwise set success to false to indicate that the 
            // user data has not been initilised 
            if( !hasRecords )
                success = false;
        }
        catch( Exception e ){
            FightClub.getInstance().printError( "PlayerDAO.initPlayer()", e.toString() );
            success = false; 
        }
        finally{
            if( renum != null ) renum.destroy(); 
            if( rs != null ) rs.closeRecordStore(); 
        }
        
        return success; 
    }
    
    /** load up the player stats **/ 
    private void initPlayerStats(){                
        _wins = new Vector(); 
        _loses = new Vector(); 
        _draws = new Vector(); 
        
        loadPlayerStats( RS_PLAYER_STATS_WINS, _wins );
        loadPlayerStats( RS_PLAYER_STATS_LOSES, _loses );
        loadPlayerStats( RS_PLAYER_STATS_DRAWS, _draws );
                
    }
    
    private void loadPlayerStats( String rsName, Vector vec ){
        RecordStore rs = null;
        RecordEnumeration renum = null; 
        
        try{
            // open record store 
            rs = RecordStore.openRecordStore( rsName, true );
            
            // obtain the enumerator and iterate through all records and store them 
            // in the vector 
            renum = rs.enumerateRecords( null, null, false ); 
            while( renum.hasNextElement() ){
                byte[] raw = renum.nextRecord();
                String data = new String( raw );
                vec.addElement( data );
            }
            
        }
        catch( Exception e ){
            FightClub.getInstance().printError( "PlayerDAO.initPlayerStats() record store " + 
                    rsName, e.toString() );
        }
        finally{
            try{
                if( renum != null ) renum.destroy(); 
                if( rs != null ) rs.closeRecordStore(); 
            }
            catch( RecordStoreException rse ){
                FightClub.getInstance().printError( "PlayerDAO.initPlayerStats() record store " + 
                    rsName, rse.toString() );
            }
        }
    }
    
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="mutators for player details">
    public String getPlayerName() {
        return _playerName;
    }

    public void setPlayerName(String playerName) {
        this._playerName = playerName;
    }

    public int getStrenth() {
        return _strenth;
    }

    public void setStrenth(int strenth) {
        this._strenth = strenth;
    }

    public int getSpeed() {
        return _speed;
    }

    public void setSpeed(int speed) {
        this._speed = speed;
    }

    public int getPlayerID() {
        return _playerID;
    }

    public void setPlayerID(int playerID) {
        this._playerID = playerID;
    }

    public boolean isPlayerInit() {
        return _playerInit;
    }

    public void setPlayerInit(boolean playerInit) {
        this._playerInit = playerInit;
    }
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="mutators for player stats" >
    
    public int getPlayerWins(){
        return _wins.size(); 
    }
    
    public Enumeration getPlayersNamesOfWins(){
        return _wins.elements(); 
    }
    
    /** add the opponent to the wins recordstore and vector **/ 
    public void addWin( String opponentName ) {
        RecordStore rs = null;
        
        try{
            rs = RecordStore.openRecordStore( RS_PLAYER_STATS_WINS, true );
            
            byte[] raw = opponentName.getBytes(); 
            rs.addRecord( raw, 0, raw.length );
            
            _wins.addElement( opponentName );
        }
        catch( Exception e ){
            FightClub.getInstance().printError( "PlayerDAO.addWin()", e.toString() );
        }
        finally{
            try{
                if( rs != null ) rs.closeRecordStore(); 
            }
            catch( RecordStoreException rse ){
                FightClub.getInstance().printError( "PlayerDAO.addWin()", rse.toString() );
            }
        } 
    }
        
    public int getPlayerLoses(){
        return _loses.size(); 
    }
    
    public Enumeration getPlayersNamesOfLoses(){
        return _loses.elements(); 
    }
    
    /** add the opponent to the loses recordstore and vector **/ 
    public void addLose( String opponentName ) {
        RecordStore rs = null;
        
        try{
            rs = RecordStore.openRecordStore( RS_PLAYER_STATS_LOSES, true );
            
            byte[] raw = opponentName.getBytes(); 
            rs.addRecord( raw, 0, raw.length );
            
            _loses.addElement( opponentName );
        }
        catch( Exception e ){
            FightClub.getInstance().printError( "PlayerDAO.addLose()", e.toString() );
        }
        finally{
            try{
                if( rs != null ) rs.closeRecordStore(); 
            }
            catch( RecordStoreException rse ){
                FightClub.getInstance().printError( "PlayerDAO.addLose()", rse.toString() );
            }
        } 
    }
    
    public int getPlayerDraws(){
        return _draws.size(); 
    }
    
    public Enumeration getPlayersNamesOfDraws(){
        return _draws.elements(); 
    }
    
    /** add the opponent to the loses recordstore and vector **/ 
    public void addDraw( String opponentName ) {
        RecordStore rs = null;
        
        try{
            rs = RecordStore.openRecordStore( RS_PLAYER_STATS_DRAWS, true );
            
            byte[] raw = opponentName.getBytes(); 
            rs.addRecord( raw, 0, raw.length );
            
            _draws.addElement( opponentName );
        }
        catch( Exception e ){
            FightClub.getInstance().printError( "PlayerDAO.addDraw()", e.toString() );
        }
        finally{
            try{
                if( rs != null ) rs.closeRecordStore(); 
            }
            catch( RecordStoreException rse ){
                FightClub.getInstance().printError( "PlayerDAO.addDraw()", rse.toString() );
            }
        } 
    }
    
    public int getPlayerFights(){
        int fights = 0;
        
        if( _wins != null )
            fights += _wins.size();
        
        if( _draws != null )
            fights += _draws.size(); 
        
        if( _loses != null )
            fights += _loses.size(); 
        
        return fights; 
    }
    
    //</editor-fold>
    
}
